package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
	"time"
)

//错误信息
const ERRSTR = "\"authentication needed: password or unlock\""
const ERRLEN = len(ERRSTR)
const TIMEFORMAT = "2006-01-02 15:04:05 -0700"
const TEMP = "%s \t %d \t %s \t %s \t %d \n"

func main() {
	var (
		counter   = make(map[string]int64)
		startTime = make(map[string]int64)
		endTime   = make(map[string]int64)
	)
	f, err := os.OpenFile("/home/lblue/Downloads/eth-err1.log", os.O_RDONLY, os.ModePerm)
	if err != nil {
		panic(err)
	}
	reader := bufio.NewReader(f)
	for {
		lines, pre, err := reader.ReadLine()
		if err != nil {
			break
		}
		if pre {
			println("beginning line")
			os.Exit(1)
		}
		s := string(lines)
		errPattern := s[len(s)-ERRLEN:]
		if errPattern == ERRSTR {
			tmp := strings.Split(s, "=")
			//攻击ip
			attackIP := strings.Split(tmp[1][:len(tmp[1])-5], ":")[0]
			attackTime := strings.Split(tmp[0], " ")[1]
			t := mustParseTime(attackTime)
			st, ok := startTime[attackIP]
			//记录开始时间
			if ok && t < st || !ok {
				startTime[attackIP] = t
			}
			//记录结束时间
			et, ok := endTime[attackIP]
			if ok && t > et || !ok {
				endTime[attackIP] = t
			}
			counter[attackIP]++
		}
	}
	//fmt.Printf("%v\n%v\n%v\n", counter, startTime, endTime)
	prettyTime(counter, startTime, endTime)
}

//解析时间
func mustParseTime(attackTime string) int64 {
	attackTime = attackTime[1 : len(attackTime)-1]
	splitTime := strings.Split(attackTime, "|")
	timeString := "2019-" + splitTime[0] + " " + splitTime[1][:len(splitTime[1])-4] + " +0800"
	t, err := time.Parse(TIMEFORMAT, timeString)
	if err != nil {
		panic(fmt.Sprintf("err in: %s, %v, %s\n", attackTime, timeString, err))
	}
	return t.Unix()
}

func prettyTime(counter map[string]int64, startTime map[string]int64, endTime map[string]int64) {
	fmt.Printf("ip \t count \t start \t end \t frequency(second/request)\n")
	for ip, count := range counter {
		start, inStart := startTime[ip]
		end, inEnd := endTime[ip]
		if !inStart || !inEnd {
			print("error in collecting ip address ", ip)
			continue
		}
		f := (end - start) / count
		ts := time.Unix(start, 0)
		te := time.Unix(end, 0)
		fmt.Printf(TEMP, ip, count, ts.String(), te.String(), f)
	}
}
